/**
 * 
 */
package speculoos.jndi.io;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import speculoos.utils.TypeHelper;
import speculoos.utils.TypeManipulator;

/**
 * This class is used to associate class instances to object/ldap serialization
 * mechanisms.
 * <p>
 * An instance of this class is associated with each JNDISource and is used to
 * associate transformation objects with actual java type of objects stored in
 * given input and output maps. The default implementation reads and writes
 * strings:
 * <ul>
 * <li>the class {@link fr.norsys.mapper.utils.TypeHelper} is used to
 * transform strings into objects,</li>
 * <li>the {@link java.lang.Object#toString()} method is used to transform
 * objects into strings.</li>
 * </ul>
 * </p>
 * 
 * @author abailly
 */
public class Object2LDAP implements ObjectIO,TypeManipulator {

	/*
	 * the type helper object used
	 */
	private TypeHelper typeHelper;

	/*
	 * map from class to ObjectIO instances
	 */
	private Map /* < Class, ObjectIO > */iomap = new HashMap();

	/**
	 * Associate the given Class object <code>cls</code> to the ObjectIO
	 * <code>io</code> serializer.
	 * 
	 * @param cls
	 *            the Class instance to handle.
	 * @param io
	 *            the serializer.
	 */
	public void setObjectIO(Class cls, ObjectIO io) {
		this.iomap.put(cls, io);
	}

	/**
	 * Returns the ObjectIO instance associated with given class.
	 * 
	 * @param cls
	 *            the Class instance to look for.
	 * @return the ObjectIO associated or null.
	 */
	public ObjectIO getObjectIO(Class cls) {
		return (ObjectIO) this.iomap.get(cls);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see fr.norsys.mapper.jndi.io.ObjectIO#toLDAP(java.lang.Object)
	 */
	public Object toLDAP(Object o) throws IOException {
		/* check in map */
		ObjectIO io = getObjectIO(o.getClass());
		if (io != null)
			return io.toLDAP(o);
		/* defaults */
		if (o instanceof String)
			return o;
		else
			return o.toString();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see fr.norsys.mapper.jndi.io.ObjectIO#fromLDAP(java.lang.Object)
	 */
	public Object fromLDAP(Class c, Object o) throws IOException {
		/* null class handling -> string conversion */
		if (c == null)
			return convert(String.class, o);
		/* check in map */
		ObjectIO io = getObjectIO(c);
		if (io != null)
			return io.fromLDAP(c, o);
		/* default handling */
		if (o.getClass() == c)
			return o;
		else
			return convert(c, o);
	}

	private Object convert(Class c, Object o) throws IOException {
		if (o instanceof String)
			return typeHelper.convert(c, (String) o);
		else
			throw new IOException("Don't know how to convert from "
					+ o.getClass() + " to " + c);
	}

	/**
	 * @return Returns the types.
	 */
	public TypeHelper getTypeHelper() {
		return typeHelper;
	}

	/**
	 * @param types The types to set.
	 */
	public void setTypeHelper(TypeHelper types) {
		this.typeHelper = types;
	}
}
